package mrpheu.demo.server.implement;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

import mrpheu.demo.basic.interfaces.IMrPheuIO;
import mrpheu.demo.basic.interfaces.IMrPheuOPC;
import mrpheu.demo.server.bean.MessageItem;
import mrpheu.demo.server.classes.ProcessBasicClient;
import mrpheu.demo.server.constants.UsingServerFlag;
import mrpheu.demo.server.interfaces.IZoneClient;
import mrpheu.demo.server.main.ServerChat;

public class ProcessTCPClient extends ProcessBasicClient implements Runnable, IMrPheuOPC, IZoneClient, IMrPheuIO {

    private Socket socket = null;
    private DataInputStream streamIn = null;
    private DataOutputStream streamOut = null;
    // private BufferedReader streamOut = null;
    private boolean off = false; // default

    public ProcessTCPClient(int id, Socket clientSocket) {
        super(id, UsingServerFlag.TCP);
        this.socket = clientSocket;
    }
    
    public boolean isOff() {
        return off;
    }
    
    public void setOff(boolean off) {
        this.off = off;
    }

    @Override
    public void run() {
        if (this.socket != null) {
            this.open();
            this.process();
            this.close();
        } else {
            System.out.println("Socket null");
        }
    }

    @Override
    public boolean open() {
        if (this.socket != null) {
            try {
                this.streamIn = new DataInputStream(
                        this.socket.getInputStream());
                this.streamOut = new DataOutputStream(
                        this.socket.getOutputStream());
            } catch (IOException e) {
                System.out.println("Get I/O " + this.socket + " fail.");
                return false;
            }
        }
        return true;
    }

    public void process() {
        this.sendIdByServer(String.valueOf(this.getId()));
        if (this.socket != null && this.streamIn != null) {
            while (!this.off) {
                String data = (String)receiveData();
                MessageItem messageItem = MessageItem.processData(data);
                try {
                    System.out.println("Insert to queue");
                    ServerChat.messageList.put(messageItem);
                } catch (InterruptedException e) {
                    System.out
                            .println("Server insert data to the queue fail!");
                }
            }
        }
    }

    public boolean close() {
        try {
            if (this.streamIn != null) {
                this.streamIn.close();
            }
            if (this.socket != null) {
                this.socket.close();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("Close client fail.");
            return false;
        }
        return true;
    }

    public void sendByClient(int sourceId, String message) throws IOException {
        this.streamOut.writeUTF("Server" + "(send by " + sourceId + "):"
                + message);
        this.streamOut.flush();
        System.out.println("Done");
    }

    public void sendIdByServer(String message) {
        try {
            this.streamOut.writeUTF(message);
            this.streamOut.flush();
            System.out.println("Done");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void update(MessageItem messageItem) {
        if (messageItem != null) {
            try {
                System.out.println("Updating...");
                this.sendByClient(messageItem.getSourceClient(),
                        messageItem.getMessage());
            } catch (IOException e) {
                System.out.println("Send " + this.getId() + " message:" + "\""
                        + messageItem.getMessage()
                        + "\"" + " fail");
            }
        }
    }

    @Override
    public boolean sendData(Object data) {
        MessageItem messageItem = (MessageItem) data;
        if (data != null) {
            try {
                this.sendByClient(messageItem.getSourceClient(),
                        messageItem.getMessage());
            } catch (IOException e) {
                return false;
            }
        }
        return true;
    }

    @Override
    public Object receiveData() {

        try {
            String line = this.streamIn.readUTF();
            System.out.println(this.socket + ": " + line);
            this.off = line.equals(".bye");
            return line;
        } catch (IOException e) {
            this.off = true;
        }
        return null;
    }
    

}
